package edu.cug.water.crawler.job.task.province;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import edu.cug.water.crawler.common.annotation.BeanField;
import edu.cug.water.crawler.common.constant.Constant;
import edu.cug.water.crawler.common.exception.RRException;
import edu.cug.water.crawler.common.utils.DateUtils;
import edu.cug.water.crawler.common.utils.EsUtils;
import edu.cug.water.crawler.job.entity.province.BeiJingRain;
import edu.cug.water.crawler.job.request.RequestUtil;
import edu.cug.water.crawler.job.task.ITask;
import edu.cug.water.crawler.job.utils.AbstractCrawlerTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static edu.cug.water.crawler.common.constant.EsConstants.TypeConstant.BEIJING_RAIN;


@Component("job:BeiJingTask")
@Slf4j
public class BeiJingTask extends AbstractCrawlerTask<BeiJingRain> implements ITask {

    @Autowired
    RequestUtil requestUtil;

    @Autowired
    EsUtils esUtils;

    @Override
    public int run(String params) throws IOException {
        init();

        ResponseEntity<String> requestBody = getRequestBody();

        int statusCodeValue = requestBody.getStatusCodeValue();
        log.info("{} response status code :{}", getClass().getName(), statusCodeValue);

        List<BeiJingRain> results = getDataFromStr(requestBody.getBody());
        log.info("{} converts results：{}", getClass().getName(), results.size());

        Boolean aBoolean = esUtils.statusJudge(esUtils.addDocuments(BEIJING_RAIN.getValue(), results));
        if (!aBoolean)
            throw new RRException(getClass().getName() + Constant.LogConstants.THE_PROCESS_OF_ES_STORE_FAILED.getValue());

        return results.size();
    }

    @Override
    protected void init() {
        super.init();
        url = "http://nsbd.swj.beijing.gov.cn/service/jinRainList/list";
        headers.set("Content-Type", "application/json;charset=UTF-8");
        headers.set("Origin", "http://nsbd.swj.beijing.gov.cn");
        headers.set("Host", "nsbd.swj.beijing.gov.cn");
        headers.set("Connection", "keep-alive");
        headers.set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
        headers.set("Referer", "http://nsbd.swj.beijing.gov.cn/csyq1.html");
        headers.set("Accept-Encoding", "gzip, deflate");
        headers.set("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7");

        JSONObject o = new JSONObject();
        o.put("queryDate", DateUtils.formatDate(new Date()));

        httpEntity = new HttpEntity<String>(o.toJSONString(), headers);
    }

    @Override
    public ResponseEntity<String> getRequestBody(){
        return requestUtil.request(url, HttpMethod.POST, httpEntity);
    }

    @Override
    public List<BeiJingRain> getDataFromStr(String requestBody) {
        if (StringUtils.isEmpty(requestBody))
            throw new RRException(getClass().getName() + Constant.LogConstants.RESPONSE_IS_NULL.getValue());

        JSONObject parse = (JSONObject)JSONObject.parse(requestBody);

        String message = parse.getString("message");
        int code = parse.getIntValue("code");
        log.info("{} parse JSON str code: {}, message: {}", getClass().getName(), code, message);

        JSONObject data = parse.getJSONObject("data");
        JSONArray rain_data = data.getJSONArray("rain_data");


        List<BeiJingRain> results = new ArrayList<>();
        // PS: 0 ~ 120条为正常数据、之后的为统计数据
        //for (int i = 0; i < rain_data.size(); i ++)
        for (int i = 0; i <= 120; i ++)
        {
            JSONObject o = (JSONObject)rain_data.get(i);

            BeiJingRain beiJingRain = new BeiJingRain();
            Field[] declaredFields = beiJingRain.getClass().getDeclaredFields();

            for (Field field : declaredFields) {
                try {
                    BeanField annotation = field.getAnnotation(BeanField.class);
                    if (annotation == null) continue;

                    field.setAccessible(true);

                    field.set(beiJingRain, o.getString(annotation.property()));
                } catch (IllegalAccessException e) {
                    throw new RRException(getClass().getName() + Constant.LogConstants.FIELD_ASSIGNMENT_ILLEGAL_ACCESS.getValue());
                }
            }
            beiJingRain.setCreateTime(DateUtils.formatDateTime(new Date()));
            results.add(beiJingRain);
        }

        return results;
    }

}
